package ar.republicagroup.gestion.dao.jpa;

import ar.republicagroup.gestion.dao.CuentaBancoDAO;
import ar.republicagroup.gestion.entities.CuentaBanco;
import ar.republicagroup.gestion.services.ChequeEstadoServices;
import ar.republicagroup.gestion.util.JComboBoxModel;
import ar.republicagroup.gestion.util.JPAUtil;
import ar.republicagroup.gestion.util.UserSession;
import ar.republicagroup.gestion.util.helpers.MapSorting;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.swing.DefaultComboBoxModel;
import org.apache.log4j.Logger;

public class CuentaBancoDAOImplJPA implements CuentaBancoDAO{
	
	
	private EntityManager em;
        static Logger log = Logger.getLogger(CuentaBancoDAOImplJPA.class);
	
	
	public CuentaBancoDAOImplJPA(){
			em = JPAUtil.getEntityManager();
	}

	@Override
	public List<CuentaBanco> findEntities() {
		TypedQuery<CuentaBanco> query = em.createQuery("SELECT cb FROM CuentaBanco cb WHERE cb.estado = 1 AND cb.id > 1",CuentaBanco.class);
		return query.getResultList();
	}

	@Override
	public String insert(CuentaBanco beanCuentaBanco) {
			String resultado = null;
		
			try{
				em.getTransaction().begin();
				em.persist(beanCuentaBanco);
				em.getTransaction().commit();
				resultado = "Se registró la cuenta bancaria";
                                log.info("Registrando cuenta bancaria "+beanCuentaBanco.getNombre());
			}catch(Exception ex){
				em.getTransaction().rollback();
				ex.printStackTrace();
				
			}
	
			return resultado;
	}

	@Override
	public String update(CuentaBanco beanCuentaBanco) {
		String resultado = null;
		
		/* BUSCAMOS EL BANCO PARA SETEARLE LOS DATOS */
	CuentaBanco mergeCuentaBanco 		= em.find(CuentaBanco.class, beanCuentaBanco.getId());
        
        
	
	if (mergeCuentaBanco!=null){
		/* SETEAMOS LOS DATOS MODIFICADOS en mergeCuentaBanco*/
		mergeCuentaBanco.setNombre(beanCuentaBanco.getNombre());
		mergeCuentaBanco.setCuentaTipoId(beanCuentaBanco.getCuentaTipoId());
		mergeCuentaBanco.setBancoId(beanCuentaBanco.getBancoId());
		mergeCuentaBanco.setNumero(beanCuentaBanco.getNumero());
		mergeCuentaBanco.setCbu(beanCuentaBanco.getCbu());
	}
	
                try{
                    em.getTransaction().begin();
                    em.merge(mergeCuentaBanco);	
                    em.getTransaction().commit();
                    resultado = "Se actualizó la cuenta";
                    log.info(UserSession.getInstance().getUser_name()+" ---> "+"Actualizando cuenta bancaria :"+beanCuentaBanco.getId());
                    }catch(Exception ex){
					em.getTransaction().rollback();
					ex.printStackTrace();
                    }
	
                return resultado;
	}
	
	

	@Override
	public CuentaBanco get(Integer id_cuentabanco) {
		return em.find(CuentaBanco.class, id_cuentabanco);
	}

	@Override
	public String delete(Integer id_cuentabanco) {
		String resultado = null;
		
		/* BUSCAMOS LA CUENTA PARA SETEARLE LOS DATOS */
		CuentaBanco deleteCuentaBanco 		= em.find(CuentaBanco.class, id_cuentabanco);
		deleteCuentaBanco.setEstado(0);		//<--- Eliminacion logica , estado = 0
		
		/* HACEMOS UN MERGE DE deleteBanco*/
		try{
				em.getTransaction().begin();
				em.merge(deleteCuentaBanco);	
				em.getTransaction().commit();
				resultado = "Cuenta eliminada";
			}catch(Exception ex){
				em.getTransaction().rollback();
				ex.printStackTrace();
			}
		
		return resultado;
	}

    @Override
    public DefaultComboBoxModel combo() {
        
        Query query                 = em.createQuery("SELECT cb FROM CuentaBanco cb WHERE cb.estado = 1 ORDER BY cb.nombre",CuentaBanco.class);
        List<CuentaBanco> cuentabancoList   = query.getResultList();
        DefaultComboBoxModel model  = new DefaultComboBoxModel();
        for(CuentaBanco cuentabanco : cuentabancoList){
            model.addElement(new JComboBoxModel(cuentabanco.getId().toString(), cuentabanco.getNombre()));
        }
        
        return model;
    }

    @Override
    public Map<CuentaBanco, Object> getTotalesPorCuenta() {
        log.info("Obteniendo totales por cuenta...");
        
        if(!em.isOpen()){ em = JPAUtil.getEntityManager();}
            Date fechaInicio = new Date();
            fechaInicio.setHours(0);
            fechaInicio.setMinutes(0);
            fechaInicio.setSeconds(0);
        
            Date fechaFin = new Date();
            fechaFin.setHours(23);
            fechaFin.setMinutes(59);
            fechaFin.setSeconds(59);
            
            /*
             SELECT cb.nombre,SUM(c.importe) FROM cheque c 
            INNER JOIN cuenta_banco cb
            ON c.cuenta_banco_id = cb.id
            WHERE c.estado = 1
            AND c.fecha_alta BETWEEN '2013-07-18 00:00:00' AND '2013-07-18 23:59:59'
            GROUP BY cb.nombre;
             */
        
            Query query = em.createQuery("SELECT c.cuentaBancoId,SUM(c.importe) FROM Cheque c WHERE  c.fechaAlta "
                    + "BETWEEN :fechaInicio AND :fechaFin AND c.estado = :chequeActivo  " 
                    + " OR (c.fechaUpdate BETWEEN :fechaInicio AND :fechaFin AND c.chequeEstadoId.id = "+ChequeEstadoServices.CHEQUE_INGRESADO + ") GROUP BY c.cuentaBancoId.nombre");
            query.setParameter("chequeActivo", 1);
            query.setParameter("fechaInicio", fechaInicio);
            query.setParameter("fechaFin",fechaFin);
            List<Object[]> results = query.getResultList();
            Map<CuentaBanco,Object> totalesPorCuentaMap = new HashMap<>();
            
            
            
            for(Object[] row : results){
                System.out.println(row[0].toString()+" "+row[1]);
                totalesPorCuentaMap.put((CuentaBanco)row[0], row[1]);
            }
            
            return totalesPorCuentaMap;
    }

    @Override
    public Map<String, Object> getTotalesPorCuentaByEstadoAndDates(int chequeEstadoId , Date fechaInicio, Date fechaFin) {
        
        log.info("Obteniendo totales por cuenta...");
        
        if(!em.isOpen()){ em = JPAUtil.getEntityManager();}
        
        fechaInicio.setHours(0);
        fechaInicio.setMinutes(0);
        fechaInicio.setSeconds(0);
        
        fechaFin.setHours(23);
        fechaFin.setMinutes(59);
        fechaFin.setSeconds(59);
        
        
        StringBuilder mysqlQuery = new StringBuilder();
        
        mysqlQuery.append("SELECT cb.nombre,SUM(ch.importe) FROM cuenta_banco cb ");
        mysqlQuery.append("INNER JOIN cheque ch ");
        mysqlQuery.append("ON cb.id = ch.cuenta_banco_id ");
        mysqlQuery.append("WHERE ch.fecha_alta BETWEEN ? AND ? ");
        mysqlQuery.append("AND ch.cheque_estado_id = ? ");
        mysqlQuery.append("GROUP BY cb.nombre ");
        
        Query query= em.createNativeQuery(mysqlQuery.toString());
        query.setParameter(1, fechaInicio);
        query.setParameter(2, fechaFin);
        query.setParameter(3, chequeEstadoId);
        
        System.out.println("query.getResultList() : "+query.getResultList().size());
        
        List<Object[]> results = query.getResultList();
        
        Map<String,Object> resultQueryMap = new HashMap<>();
        
        for(Object[] row : results){
            resultQueryMap.put(row[0].toString(), row[1]);
        }
        
        Map resultMapSorted = MapSorting.sortByKeys(resultQueryMap);
        return resultMapSorted;
    }

}
